#include<iostream>
#include"func.h"
#include<opencv2/imgcodecs.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc.hpp>
#include<opencv2/objdetect.hpp>
#include<opencv2/opencv.hpp>
#include<opencv2/ximgproc.hpp>
#include<string>
#include<vector>
#include<fstream>

using namespace std;
using namespace cv;
using namespace cv::ml;

void jianduxuexi()
{
    Mat img=imread("/home/zhanjiabin/桌面/task/study/9b2f68e9ec0107689823e46f5d0941b.jpg");
    Mat gray;
    cvtColor(img,gray,COLOR_BGR2GRAY);

    //分割为5000个cells
    Mat images=Mat::zeros(5000,400,CV_8UC1);
    Mat labels=Mat::zeros(5000,1,CV_8UC1);

    int index=0;
    Rect numberimg;
    numberimg.x=0;
    numberimg.height=1;
    numberimg.width=400;
    for(int row=0;row<50;row++)
    {
        //在图像中分割出209*20图像作为独立像素
        int label=row/5;
        int datay=row*20;
        for(int col=0;col<100;col++)
        {
            int datax=col*20;
            Mat number=Mat::zeros(Size(20,20),CV_8UC1);
            for(int x=0;x<20;x++)
            {
                for(int y=0;y<20;y++)
                {
                    number.at<uchar>(x,y)=gray.at<uchar>(x+datay,y+datax);
                }
            }
            //将第二幅图转换成行数据
            Mat row=number.reshape(1,1);
            cout<<"提取第"<<index+1<<"个数据"<<endl;
            numberimg.y=index;
            //添加到总数据中
            row.copyTo(images(numberimg));
            //记录每个图像对应数字标签
            labels.at<uchar>(index,0)=label;
            index++;
        }
    }
    imwrite("/home/zhanjiabin/桌面/task/study/所有数据排列结果.png",images);
    imwrite("/home/zhanjiabin/桌面/task/study/标签.png",labels);

    //加载训练数据集合
    images.convertTo(images,CV_32FC1);
    labels.convertTo(labels,CV_32SC1);
    Ptr<ml::TrainData> tdata=ml::TrainData::create(images,ml::ROW_SAMPLE,labels);//创建训练模型函数(样本数据矩阵,排列方式标志，标签矩阵)

    //创建k近邻类
    Ptr<KNearest> knn=KNearest::create();
    knn->setDefaultK(5);//每个类别拿出5个数据
    knn->setIsClassifier(true);//进行分类

    //训练数据
    knn->train(tdata);
    //保存训练结果
    knn->save("/home/zhanjiabin/桌面/task/study/knn_model.yml");

    //输出运行结果显示
    cout<<"已完成训练和保存"<<endl;
    
    waitKey(0);

}

void jiazaiyml()
{
    //家在knnf分类器
    Mat data=imread("/home/zhanjiabin/桌面/task/study/所有数据排列结果.png",IMREAD_ANYDEPTH);
    Mat labels=imread("/home/zhanjiabin/桌面/task/study/标签.png",IMREAD_ANYDEPTH);
    data.convertTo(data,CV_32FC1);
    labels.convertTo(labels,CV_32SC1);
    Ptr<KNearest>knn=Algorithm::load<KNearest>("/home/zhanjiabin/桌面/task/study/knn_model.yml");

    //查看分类结果
    Mat result;
    knn->findNearest(data,5,result);

    //统计分类结果与真实结果相同的数目
    int count=0;
    for(int row=0;row<result.rows;row++)
    {
        int predict=result.at<float>(row,0);
        if(labels.at<int>(row,0)==0)
        {
            count=count+1;
        }
    }
    float rate=1.0*count/result.rows;
    cout<<"分类正确性"<<rate<<endl;

    VideoCapture cap(0);
    Mat testimg,ti2;
    Mat testdata;
    Rect rect;
    Mat onedata,twodata;
    Mat result2;
    

    while(1)
    {
        cap.read(testimg);
        imshow("testimg",testimg);

        //缩小到20*20
        resize(testimg,testimg,Size(20,20));
        testdata=Mat::zeros(2,400,CV_8UC1);
        
        rect.x=0;
        rect.y=1;
        rect.height=1;
        rect.width=400;
        onedata=testimg.reshape(1,1);
        // onedata.copyTo(testdata(rect));
        rect.y=1;

        //数据类型转换
        testdata.convertTo(testdata,CV_32F);

        //进行识别预测
        knn->findNearest(testdata,5,result2);

        //查看预测结果
        for(int i=0;i<result2.rows;i++)
        {
            int predict=result2.at<float>(i,0);
            cout<<"预测结果"<<predict<<endl;
        }

        waitKey(1);

    }


}

void kjunzhijulei()
{
    Mat img=imread("/home/zhanjiabin/桌面/task/study/test.jpg");

    Vec3b colorlut[6]=
    {
        Vec3b(0,0,255),
        Vec3b(0,255,0),
        Vec3b(255,0,0),
        Vec3b(0,255,255),
        Vec3b(255,0,255),
        Vec3b(255,255,0),
    };

    //图像尺寸
    int width=img.cols;
    int height=img.rows;

    //初始化定义
    int sampleCount=width*height;

    //将图像矩阵数据转换为每行一个数据
    Mat sample_data=img.reshape(3,sampleCount);
    Mat data;
    sample_data.convertTo(data,CV_32F);

    //kmens()进行分类
    int number=3;//分割后颜色种类
    Mat labels;
    TermCriteria cirteria=TermCriteria(TermCriteria::EPS+TermCriteria::COUNT,10,0.1);
    kmeans(data,number,labels,cirteria,number,KMEANS_PP_CENTERS);

    //显示图像分割结果
    Mat result=Mat::zeros(img.size(),img.type());
    for(int row=0;row<height;row++)
    {
        for(int col=0;col<width;col++)
        {
            int index=row*width;+col;
            int label=labels.at<int>(index,0);
            result.at<Vec3b>(row,col)=colorlut[label];
        }

    }
    imshow("原图",img);
    imshow("分割后图像",result);
    waitKey(0);

}
